﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using SharedGenomics.Workbench.Core;
using SharedGenomics.Workbench.Presenters;
using SharedGenomics.Workbench.Views;
using SharedGenomics.Workbench.Services;
using SharedGenomics.Workbench.Tests.TestObjects;
using SharedGenomics.Annotations;

namespace SharedGenomics.Workbench.Tests.Core
{
    [TestClass]
    public class PresenterFactoryIntegrationTests
    {
        private IUnityContainer container;
        private PresenterFactory presenterFactory;

        [TestInitialize]
        public void Setup()
        {
            this.container = new UnityContainer();
            this.InitialiseContainer(container);

            this.presenterFactory = new PresenterFactory(container);
            this.presenterFactory.AddCreationStage<CachePresenterInitialisationStage>();
            this.presenterFactory.AddCreationStage<BuildUpPresenterInitialisationStage>();
            this.presenterFactory.AddCreationStage<CreationPresenterInitialisationStage>();
            this.presenterFactory.AddCreationStage<InitialiseActionPresenterInitialisationStage>();

            AnnotationWrapperPresenterInitialisationStage annotationWrapperStage = new AnnotationWrapperPresenterInitialisationStage();
            annotationWrapperStage.WrapPresenter<AnnotationStubPresenter>();

            this.presenterFactory.AddCreationStage(annotationWrapperStage);
        }

        [TestMethod]
        public void ShouldCreateNewPresenter()
        {
            var presenter = this.presenterFactory.Get<StubPresenter>();
            Assert.IsNotNull(presenter);
            Assert.IsInstanceOfType(presenter, typeof(StubPresenter));
        }

        [TestMethod]
        public void ShouldExecuteInitialisationAction()
        {
            var presenter = this.presenterFactory.Get<StubPresenter>(false, p => p.SnapshotOnOpen = true);
            Assert.IsNotNull(presenter);
            Assert.IsInstanceOfType(presenter, typeof(StubPresenter));
            Assert.IsTrue(presenter.SnapshotOnOpen);
        }

        [TestMethod]
        public void ShouldBuildUpExisting()
        {
            var presenter = new StubPresenterWithDependency("abc");
            var resolved = this.presenterFactory.Get(false, presenter);

            Assert.AreSame(presenter, resolved);
            Assert.IsNotNull(presenter.InjectedDependency);
        }

        [TestMethod]
        public void ShouldWrapPresenter()
        {
            var presenter = this.presenterFactory.Get<AnnotationStubPresenter>(false, p => p.SnapshotOnOpen = true);
            Assert.IsInstanceOfType(presenter, typeof(AnnotationWrapperPresenter));
            
            //NOTE: the annotation wrapper presenter SnapshotOnOpen is simply passed from the wrapped presenter. Since the initialisation action sets this to true
            //the wrapper should also return true for this property
            Assert.IsTrue(presenter.SnapshotOnOpen);
        }

        [TestMethod]
        public void ShouldFetchFromCache()
        {
            var first = this.presenterFactory.Get<StubPresenter>(true, p => p.SnapshotOnOpen = true);
            var second = this.presenterFactory.Get<StubPresenter>();

            Assert.AreSame(first, second);
        }

        private void InitialiseContainer(IUnityContainer c)
        {
            Rhino.Mocks.MockRepository mocks = new Rhino.Mocks.MockRepository();
            c.RegisterType<StubPresenter>();
            c.RegisterInstance(mocks.Stub<IAnnotationWrapperView>());
            c.RegisterInstance(mocks.Stub<IAnnotationSessionManager>());
            c.RegisterInstance(mocks.Stub<IEventBroker>());
            c.RegisterInstance(mocks.Stub<IAnnotationNotifier>());
            c.RegisterInstance(mocks.Stub<IBackgroundExecutor>());
        }
    }
}
